feat(token-id-capture): deliver rebuilt trajectories safely - #2126
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
74a48d6 to
71de7c5
Compare
71de7c5 to
5c317c1
Compare
5c317c1 to
58cde9d
Compare
f5fa8c6 to
06bb256
Compare
06bb256 to
a28b020
Compare
cmunley1
left a comment
There was a problem hiding this comment.
left a question above, but i think its unlikely in normal cases and we could follow up unless you want to reply there now.
|
/claude review |
|
SHIP — no reliability concerns. Reviewed the token-capture delivery step and its wiring into
Test coverage is real and exercises masking, no-capture-key, nothing-recorded, mixed native/external batches, retention, and stale-record clearing. NOTE (non-blocking, author's call): |
|
/claude review |
|
Review incomplete: the PR revision changed during review. The captured base ( |
|
/claude review |
| An unusable build has no rebuilt response and sets ``mask_sample``. | ||
| """ | ||
| if source is None or rollout_carries_token_ids(result): | ||
| return None |
There was a problem hiding this comment.
With all_agents=True, if capture records are written, this early return skips the snapshot retirement https://github.com/NVIDIA-NeMo/Gym/pull/2126/changes#diff-4ed3026c5b1fe1967854548a34299c33ba36c8fd55c7cd2249324108dd0a550cR915, so those redundant records may accumulate. Should we avoid capture for agents who provide the token ids or still retire their captured snapshot?
A rollout's records are read, built into one contiguous response, and swapped in for response.output, so a trainer reads response.output the same way for a native agent and an external harness. The step takes the record and a TokenSource, and nothing else. Both belong to the caller, so every configuration question stays on the side that owns it: Gym's rollout collection resolves its source from Gym's config, and a training framework staging records through its own data plane passes its own source and never reads Gym's config. That is what makes the step shared rather than Gym's alone; a caller driving run_examples gets the same behaviour without reimplementing it. What a rollout needs is read from the rollout. An item already carrying token ids holds what the policy sampled, so that rollout is left alone; without them, the recorded ids are attached. A batch can therefore mix native agents and external harnesses, and a native agent moving onto capture simply stops arriving with ids and starts being rebuilt, with no config change anywhere. It also makes the step idempotent, since a rebuilt rollout carries ids. Records are cleared before dispatch, because rollout ids are deterministic and a store appends, and retired through the source once consumed. A rollout that lost a call is masked rather than trained on with a hole, reported as one field, mask_sample, at the top of the record: a consumer decides by reading it and nothing else. The metrics dict keeps the reasons, not the verdict. token_id_capture.rebuild_response says whether Gym reads records back at all. Off, Gym stops after the write and the caller reads through its own source; without it, a run capturing to its own transport has Gym reading a store nothing wrote to. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Resolve paired sources for readback and delay conditional capture retirement until the rebuilt rollout is fsynced, preserving masked evidence and newer attempts. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Use lifecycle terminology that states when rollout records become immutable without implying that durable delivery or retirement already completed. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
State the freeze, rebuild, handoff, and conditional retirement boundaries directly. Keep retention and masking comments aligned with the implementation. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Use the same static agent selection as request routing when clearing and rebuilding capture records. Tokenless agents that did not opt in remain ordinary evaluation rollouts. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Use caller-owned installed sources without closing them and fail before dispatch when selected rollouts cannot be rebuilt. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Record pre-dispatch call intent and preserve evidence when capture or retirement cannot complete, so consumers mask incomplete rollouts instead of training through silent holes. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Attaches a safely rebuilt token trajectory to each participating rollout and retires capture evidence only after durable handoff. This PR also owns the durable capture lifecycle used by the later lineage and prefix-supply PRs.
Capture custody and delivery
sequenceDiagram participant M as Model worker participant S as TokenSink / TokenSource backend participant C as Rollout collector or framework participant B as Trajectory builder participant D as Durable downstream M->>S: begin_call(rollout_id, model_call_id) when supported Note over M,S: Failure occurs before generation - a dangling intent identifies a lost entry M->>M: run inference and build TokenEntry M->>S: await put(TokenEntry) S-->>M: entry durable M-->>M: return model response C->>S: freeze(rollout_id) S-->>C: TokenCaptureSnapshot(entries, incomplete, snapshot_id, version) C->>B: rebuild frozen snapshot alt incomplete, malformed, ambiguous, split, or empty B-->>C: mask_sample=true and diagnostics Note over C,S: retain evidence else one safe trainable chain B-->>C: rebuilt response and metrics C->>D: write rebuilt rollout D-->>C: durable acknowledgement C->>S: drop(rollout_id, snapshot_id, version) S-->>C: true only if the frozen version is still current endA write racing
freezemay become durable, but it advances the version so a staledropcannot erase it. Retirement keeps a tombstone until operator-controlled garbage collection, preventing an old worker from recreating a retired rollout.Summary
token_id_captureconfiguration orall_agents; tokenless nonparticipants remain ordinary evaluation rollouts.TokenSink.putas an awaited durability boundary and supports optional pre-dispatchbegin_callcustody. A dangling intent makes the frozen snapshot incomplete when bothputandmark_incompletefail.snapshot_idand version after downstream durability.max_mask_fractioncan stop a run that produces too many masked rollouts.sweep_retiredfor explicit tombstone cleanup.Depends on #2125. The integration guide begins in #2341.